package com.coderman.youpinshop.stock.bo;

import com.coderman.youpinshop.stock.dataobject.StockDO;
import com.coderman.youpinshop.stock.enums.StockOperationEnum;
import lombok.Builder;
import lombok.Data;

import java.util.Date;

/**
 * Description:
 * DDD视角下的库存业务对象
 * date: 2022/1/15
 *
 * @author shenshuai
 * @version 1.0.0
 * @since JDK 1.8
 */
@Data
@Builder
public class StockDDDBO {
    /**
     * 库存编码
     */
    private String stockCode;
    /**
     * 商品ID
     */
    private Long itemId;

    /**
     * 仓库ID
     */
    private String repositoryId;

    /**
     * 库存数量
     */
    private Integer quantity;


    /**
     * 版本号
     */
    private Integer version;


    /**
     * 扣减库存
     *
     *
     * @param deductCount
     * @return 返回扣减后的库存数量
     *
     * 这块可能需要注意的是在争论贫血模型，充血模型的时候，由于事先界定了领域对象与service,dao的访问关系
     * 所以这个行为方法算某些文章的贫血模型还是充血模型其实可能具有歧义，当然我个人的观点是充血模型，但是可能比较弱
     * 在这篇文章里可以找到详细的区别：https://www.cnblogs.com/yinhaiming/articles/1564843.html
     * 但是如果你看不懂也没关系，业务实体BO里有点方法，但是不多你就认为是充血的就行，没必要分太细。
     *
     */
    public Integer deduct(Integer deductCount){
        this.quantity = this.quantity - deductCount;
        return this.quantity;
    }

    /**
     * 构建库存操作记录
     * 关于这个转换函数放在BO上可能不是特别合理，毕竟这不是StockBO本身的业务行为，负责记录业务日志变化的场景
     * 应该由日志上下文来承接，当然如果BO上的业务行为不多这么做也许可以接受，后面会具体分析这么做的一些理论或者观念
     *
     * @param stockOperationEnum
     * @param afterQuantity
     * @return
     */
    public StockRecordBO buildRecord(StockOperationEnum stockOperationEnum,Integer afterQuantity){
        return StockRecordBO.builder()
                .beforQuantity(this.quantity)
                .afterQuantity(afterQuantity)
                .operationCode(stockOperationEnum.getCode())
                .stockCode(this.stockCode)
                .operationDate(new Date())
                .build();
    }


    /**
     * 这里将do转换成BO进行领域行为操作
     * @param stockDO
     * @return
     */
    public static StockDDDBO convertFromDO(StockDO stockDO){
        if(stockDO == null){
            return null;
        }
        return StockDDDBO.builder()
                .stockCode(stockDO.getStockCode())
                .itemId(stockDO.getItemId())
                .quantity(stockDO.getQuantity())
                .version(stockDO.getVersion())
                .repositoryId(stockDO.getRepositoryId()).build();
    }


}
